package com.sl.core.engine.meta.valuemeta;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Pair;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.TypeUtil;
import com.sl.core.utils.JsonUtil;
import com.sl.core.engine.domain.ProcessBaseObj;
import com.sl.core.engine.meta.row.ProcessRowDescriptor;
import com.sl.core.engine.step.rowfrom.ProcessCompPutRowFrom;
import org.apache.hop.core.row.IRowMeta;
import org.apache.hop.core.row.IValueMeta;

import java.lang.reflect.Type;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class ValueMetaConvert {

    public static Map<String, Object> beanToMapOrFinf(Object result) {
        if (ObjectUtil.isNull(result)) {
            return null;
        }
        if (result instanceof Map) {
            return (Map<String, Object>) result;
        }


        if (ClassUtil.isSimpleTypeOrArray(result.getClass())) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("args0", result);
            return map;
        }

        if (result instanceof Collection<?> r) {
            return beanToMapOrFinf(CollUtil.get(r, 0));
        }

        return JsonUtil.toMap(JsonUtil.toStr(result), String.class, Object.class);
    }

    public static Object beanToMapOrCollection(Object result) {
        if (ObjectUtil.isNull(result)) {
            return null;
        }
        if (result instanceof Map) {
            return result;
        }
        if (result instanceof Collection<?>) {
            return result;
        }

        Map<String, Object> map = new LinkedHashMap<>();
        map.put("args0", result);

        //后续可能需要进行类型转换

        return map;
//        if (result instanceof Collection<?> r) {
//            return beanToMap(CollUtil.get(r, 0));
//        }
//
//        return JsonUtil.toMap(JsonUtil.toStr(result), String.class, Object.class);
    }

    public static Object objToBean(Type dataClass, Object param) {

        //如果bean为空 直接返回
        if (ObjectUtil.isNull(dataClass)) {
            return param;
        }
        //如果参数为空直接返回null
        if (ObjectUtil.isNull(param)) {
            return null;
        }


        //判断类本身
        Class<?> aClass = TypeUtil.getClass(dataClass);
        if (ProcessCompPutRowFrom.class.isAssignableFrom(aClass)) {
            return param;
        }
        //获取范型， 如果是List的话 需要
        Type typeArgument = TypeUtil.getTypeArgument(dataClass);


        //如果需要的是一个Map 则直接返回了，不需要对二级做操作
        if (aClass.equals(Map.class)) {
            if (param instanceof Map) {
                return param;
            } else if (param instanceof Collection<?> p) {
                return JsonUtil.toBean(JsonUtil.toStr(CollUtil.get(p, 0)), JsonUtil.getJavaType(dataClass));
            } else {
                return JsonUtil.toBean(JsonUtil.toStr(param), JsonUtil.getJavaType(dataClass));
            }
            //如果是一个List 那么就需要获取范型
        } else if (aClass.equals(List.class)) {
            //有范型 并且不是object
            if (ObjectUtil.isNotNull(typeArgument) && !typeArgument.equals(Object.class)) {
                return objToBean(typeArgument, param);
            } else {
                return param;
            }
            //如果需要的是一个Object的话 也直接返回去
        } else if (aClass.equals(Object.class)) {
            return param;
            //如果是不需要参与转换的也直接返回
        } else if (aClass.equals(ProcessBaseObj.class)) {
            //需要转换一把
            return JsonUtil.toBean(JsonUtil.toStr(param), JsonUtil.getJavaType(dataClass));

        } else if (aClass.equals(String.class)) {
//            if (param instanceof Map m) {
//                Object b = MapUtil.get(m, "args0", Object.class);
//                return JsonUtil.toStr(b);
//            }
            return JsonUtil.toStr(param);

        } else if (!ClassUtil.isBasicType(aClass)) {
            Object value = null;
            if (param instanceof Map m) {
                value = compareClass(m, aClass);
            } else {
                value = JsonUtil.toBean(JsonUtil.toStr(param), JsonUtil.getJavaType(dataClass));
            }
            return value;
        } else {
            throw new RuntimeException("无法转换的类型，请更改组件范型");
        }
    }

    private static Object compareClass(Map<String, Object> param, Class<?> aClass) {
        for (Map.Entry<String, Object> so : param.entrySet()) {
            Object value = so.getValue();

            if (aClass.isAssignableFrom(value.getClass())) {
                return value;
            }
            if (value.getClass().isAssignableFrom(aClass)) {
                return value;
            }

            if (value instanceof Map v) {
                Object o = compareClass(v, aClass);
                if (ObjectUtil.isNotNull(o)) {
                    return o;
                }
            } else if (value instanceof List c) {
                for (Object obj : c) {
                    if (obj instanceof Map vv) {
                        Object o = compareClass(vv, aClass);
                        if (ObjectUtil.isNotNull(o)) {
                            return o;
                        }
                    }
                }
            }
        }
        return null;
    }


    public static Pair<Object[], IRowMeta> mapToRowAndMeta(Map<String, Object> map) {

        Object[] objects = new Object[map.size()];
        if (MapUtil.isEmpty(map)) {
            return new Pair<>(objects, null);
        }
        Integer i = 0;
        ProcessRowDescriptor rowMetaInterface = new ProcessRowDescriptor();
        List<IValueMeta> valueMetaInterfaces = rowMetaInterface.convertMetaInterface(map);
        rowMetaInterface.setValueMetaList(valueMetaInterfaces);

        for (Map.Entry<String, Object> entry : map.entrySet()) {
            Object value = entry.getValue();
            objects[i++] = value;

        }
        return new Pair<>(objects, rowMetaInterface);
    }

    public static Object[] objToRow(Object obj) {

        Map<String, Object> map = null;
        if (obj instanceof Map<?, ?>) {
            map = (Map<String, Object>) obj;
        } else {
            map = JsonUtil.toMap(obj);
        }

        Object[] objects = new Object[map.size()];
        if (MapUtil.isEmpty(map)) {
            return objects;
        }
        Integer i = 0;
        ProcessRowDescriptor rowMetaInterface = new ProcessRowDescriptor();
        List<IValueMeta> valueMetaInterfaces = rowMetaInterface.convertMetaInterface(map);
        rowMetaInterface.setValueMetaList(valueMetaInterfaces);

        for (Map.Entry<String, Object> entry : map.entrySet()) {
            Object value = entry.getValue();
            objects[i++] = value;

        }
        return objects;
    }

    public static Object[] mapToRow(Map<String, Object> map) {

        Object[] objects = new Object[map.size()];
        if (MapUtil.isEmpty(map)) {
            return objects;
        }
        Integer i = 0;
        ProcessRowDescriptor rowMetaInterface = new ProcessRowDescriptor();
        List<IValueMeta> valueMetaInterfaces = rowMetaInterface.convertMetaInterface(map);
        rowMetaInterface.setValueMetaList(valueMetaInterfaces);

        for (Map.Entry<String, Object> entry : map.entrySet()) {
            Object value = entry.getValue();
            objects[i++] = value;

        }
        return objects;
    }
}
